/** @file Pipeline.cc
 * Implementation of class Pipeline.
 */
#include <iostream>
#include <fcntl.h>		// for: O_RDONLY, O_CREAT, O_WRONLY, O_APPEND
#include <signal.h>		// for: signal, SIG*
#include "asserts.h"
#include "unix_error.h"
#include "Pipeline.h"
#include "unistd.h"
#include <sys/wait.h>
using namespace std;


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

Pipeline::Pipeline() :
		background(false) {
}

void Pipeline::addCommand(Command *cp) {
	require(cp != 0);
	commands.push_back(cp);
}

Pipeline::~Pipeline() {
	for (vector<Command*>::iterator i = commands.begin(); i != commands.end();
			++i)
		delete *i;
}

bool Pipeline::isEmpty() const {
	return commands.empty();
}



// Execute the commands in this pipeline in parallel
void Pipeline::execute() {
	//cerr << "Pipeline::execute\n";//DEBUG

	// Because we want the shell to wait on the rightmost process only
	// we must created the various child processes from the right to the left.
	// Also see: pipe(2), fork(2), dup2(2), dup(2), close(2), open(2), signal(2).
	// Maybe also usefull for debugging: getpid(2), getppid(2).


	//signal(SIGINT,signal_callback_handler);


	size_t j = commands.size();		// for count-down

	int pipes[2];

	for (vector<Command*>::reverse_iterator i = commands.rbegin();
			i != commands.rend(); ++i, --j) {

		Command *cp = *i;

		if (j == 1) {
			cp->execute();
		} else {

			if (pipe(pipes) == -1) {
				throw unix_error("pipe");
			}

			switch (fork()) {

			default: // ik ben de rechter tak
					 // koppel onze pipe aan invoer
				dup2(pipes[0], 0);
				close(pipes[0]);
				close(pipes[1]);

				cp->execute();
				notreached();
				break;

			case 0: // handle the entire left hand side of the pipeline
					// koppel onze pipe aan uitvoer
				dup2(pipes[1], 1);
				close(pipes[0]);
				close(pipes[1]);
				break;

			case -1:
				throw unix_error("fork");
				break;
			}
		}
	}

}

